#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QMessageBox>
#include <QSettings>
#include <vector>
#include <Windows.h>
#include <tchar.h>
#include <Mouse3DInput.h>
#include <TrinamicCommunication.h>
#include <QKeyEvent>
#include <QTimer>
#include <NationalInstruments.h>
#include <MatroxImagingLibrary.h>
#include <QDebug>
#include <QFile>
#include <QFileDialog>
#include "systemkeyboardreadwrite.h"
#include <QElapsedTimer>
#include <manual.h>

#include <plotwindow.h>

#define MULTIPHOTON_VERSION  101
#define PI 3.1415926

//keyboard input
#define KEY_XPOS    0
#define KEY_XNEG    1
#define KEY_YPOS    2
#define KEY_YNEG    3
#define KEY_ZPOS    4
#define KEY_ZNEG    5
#define KEY_TPOS    6
#define KEY_TNEG    7
#define KEY_TTPOS    8
#define KEY_TTNEG    9

//wheel-type input, (w/ ctrl key)
#define KEY_XWHEELPOS  20
#define KEY_XWHEELNEG  21
#define KEY_YWHEELPOS  22
#define KEY_YWHEELNEG  23
#define KEY_ZWHEELPOS  24
#define KEY_ZWHEELNEG  25
#define KEY_TWHEELPOS  26
#define KEY_TWHEELNEG  27

#define KEY_OCULAR           50
#define KEY_STARTSCANNING    51
#define KEY_MONITOR          52
#define KEY_ACQUIRE          53

namespace Ui {
    class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

    Ui::MainWindow *ui;

public slots:
    void 	OnMove(std::vector<float>& motionData);
    void        PositionQuery();
    void        ZStackTakeNextStep();

    void        ScriptEngine();
    //void OnKeyPressed ( byte* keysDepressed, int vkCode );

    void        OnKeyPressed(QKeyEvent* e, bool pressed);
    void        OnShuttleMoved(DWORD event, UCHAR status, WORD type, WORD devicenumber);
    void        fnChangeFocus(QWidget* a,QWidget* b);

    void        TimerTasks();

public:

    QElapsedTimer timer;
    //STARTUP
    void        OnLoseFocus();
    void        Initialize();
    void        Shutdown();
    void        InitializeTrinamic(bool ShutdownOnFail);
    void        ShutdownTrinamic();
    void        LoadSettings();
    void        SaveSettings();
    void        UpdateInterface();
    void        UpdateFilenameToUi();
    void        SetExtTrigger(bool trig);
    void        SetRetrigger(bool trig);
    void        SaveDelay();

    //MAJOR SUBCOMPONENTS
    Mouse3DInput* m3dConnexion;
    TrinamicCommunication* mTrinamic;
    NationalInstruments* mNationalInstruments;
    MatroxImagingLibrary* mMatroxImagingLibrary;
    PlotWindow* pw;

    QSettings*  settings;

    int configuration;
    bool bNationalInstruments;
    bool bTrinamic;
    bool bResonantScanning;
    bool bMatrox;
    bool bCommPortOpen;
    bool bInitialized;

    QFile qDebugLog;

    int  nKeymap[100];

    void        TriggerScanImage();

    //BASIC ACQUISITION

    void        StartMonitor();
    void        StopMonitor();
    void        StartAcquire();
    void        StopAcquire();
    void        OutputReport(bool bSavemonitor);
    void        TrinamicUpdateLCD();
    void        TrinamicUpdateDebug();
    void        UpdateZoom(double fast,double slow, double laser);
    void        SetMagnification(int mag);
    void        UpdateMatrox();
    void        UpdateFilename();
    void        MoveFirgelli(int setposition, int id);
    HANDLE      OpenSerial(LPCWSTR ComName, DWORD Baudrate);
    void        CloseSerial(HANDLE handle);

    void        LoadPowerCalibration();
    void        DoPowerCalibration();
    void        Retract();
    double      dPowerCalibration[10];
    double      dRetraction;
    int         nRetractCount;
    int         nResetCount;


    //NATIVE STACK FUNCTIONS
    int         nZStackCurrentSlice;
    int         nZStackTotalSlices;
    double      dZStackPitch;
    int         nMotionSettleMillseconds;
    int         nAcquisitionTimeMilliseconds;
    bool        bAcquiringStack;

    double      dPreciseStackStart;
    double      dPreciseStackFinish;
    bool        bStackPreciseReady;
    bool        bAcquiringStack_Precise;
    bool        bAcquiringStack_Fast;
    bool        bAcquiringMosaic;

    //External stack
    void        AcquireZStack(double ZPitchMicrons, int nFrames);
    void        StopZStack();

    //Precise stack
    void        UpdatePreciseStack();
    void        AcquireZStack_Precise(double ZPitchMicrons, int nFrames);
    void        StopZStack_Precise();

    //Fast stack
    void        AcquireZStack_Fast(double depth, int speed);
    void        StopZStack_Fast();

    //2D Mosaic
    void        Acquire2DMosaic(int imagesx, int imagesy, double stridex, double stridey);
    void        Acquire3DMosaic(int imagesx, int imagesy, int imagesz,
                                double stridex, double stridey, double stridez,
                                double startpower, double endpower);

    void        Acquire3DMosaicFast(int imagesx,
                    int imagesy,
                    double zstart,
                    double zend,
                    double stridex,
                    double stridey,
                    int zspeed,
                    double startpower,
                    double endpower
                    );

    void        StopMosaic();

    void        UpdateROIPlots(double* list);
    void        UpdateHistogramPlots(double* red, double* green, double* blue);
    QVector<double> plothistogram[3];
    QVector<double> plothistogramx;
    QVector<double> plotvector[24];
    QVector<double> plotvectorx;


    //SCRIPTING ENGINE
    //called after scriptengine initiates move.  checks to see if motion complete
    void        MoveTimer();

    void        ReadScriptFile();
    void        ScriptFlush();

    QTimer mTimerScript;
    //called (returns asynchronously hopefully) to give script commands
    void        ScriptCmd(QString cmd, double dA, double dB, double dC);
    bool bRunningScript;
    QStringList CurrentScript;
    QString LastCommand;
    double LastdA, LastdB, LastdC;
    bool bWaitingForLastFinish;

    //ASYNCH TIMERS
    QTimer mTimerPosition;
    QTimer mTimerStack;
    QTimer mTimerShuttle;

    //solves problems with multithreading
    QTimer mTimerTasks;

    bool bTaskStopMonitor;
    bool bTaskStartMonitor;
    bool bTaskStopAcquire;
    bool bTaskStartAcquire;
    bool bTaskUpdateUi;


    //USER INTERFACE
private slots:
    void on_radioButton_toggled(bool checked);

    void on_radioButton_2_toggled(bool checked);

    void on_motionscale_dial_valueChanged(int value);

    void on_pushButton_relativeorigin_clicked();

    void on_radioButton_relativemode_clicked(bool checked);

    void on_radioButton_absolutemode_clicked();

    void on_pushButton_acquirezstack_clicked();

    void on_pushButtonMonitor_clicked();

    void on_pushButtonAcquire_clicked();

    void on_checkBox_savemonitor_clicked();

    void on_checkBox_exttrigger_clicked();

    //void on_horizontalSlider_fastzoom_actionTriggered(int action);

    //void on_horizontalSlider_slowzoom_actionTriggered(int action);

    void on_spinBox_extrazoom_editingFinished();

    void on_checkBox_fastblank_clicked();

    void on_checkBox_slowblank_clicked();

    void on_checkBox_fovpower_clicked();

    void on_checkBox_disablescanner_clicked();

    void on_spinBox_sumframes_editingFinished();

    void on_spinBox_sumpixels_editingFinished();

    /*
    void on_horizontalSlider_fastzoom_valueChanged(int value);

    void on_horizontalSlider_slowzoom_valueChanged(int value);
    */

    void on_checkBoxMedian_clicked(bool checked);

    void on_checkBoxMean_clicked(bool checked);

    void on_checkBoxInvert_clicked(bool checked);

    void on_checkBoxLog_clicked(bool checked);

    void on_spinBox_sumframes_valueChanged(int arg1);

    void on_spinBox_sumpixels_valueChanged(int arg1);

    void on_doubleSpinBox_fastzoom_valueChanged(double arg1);

    void on_doubleSpinBox_slowzoom_valueChanged(double arg1);

    void on_checkBox_savemonitor_clicked(bool checked);

    void on_checkBox_exttrigger_clicked(bool checked);

    void on_checkBox_retriggerable_clicked(bool checked);

    void on_spinBox_frames_valueChanged(int arg1);

    void on_comboBox_linesperframe_currentIndexChanged(const QString &arg1);

    void on_spinBox_pulsedelay_valueChanged(int arg1);

    void on_spinBox_min_1_valueChanged(int arg1);

    void on_spinBox_max_1_valueChanged(int arg1);

    void on_spinBox_min_2_valueChanged(int arg1);

    void on_spinBox_max_2_valueChanged(int arg1);

    void on_spinBox_min_3_valueChanged(int arg1);

    void on_spinBox_max_3_valueChanged(int arg1);

    void on_spinBox_min_4_valueChanged(int arg1);

    void on_spinBox_max_4_valueChanged(int arg1);

    void on_checkBox_rotationmode_clicked(bool checked);

    void on_doubleSpinBox_objectiveangle_valueChanged(double arg1);

    void on_actionExit_triggered();

    void on_checkBoxSine_clicked(bool checked);

    void on_checkBoxColor_clicked(bool checked);

    void on_lineEdit_dataset_editingFinished();

    void on_reset_display_clicked();

    void on_doubleSpinBox_gain1_valueChanged(double arg1);

    void on_doubleSpinBox_gain2_valueChanged(double arg1);

    void on_doubleSpinBox_gain3_valueChanged(double arg1);

    void on_doubleSpinBox_gain1_2_valueChanged(double arg1);

    void on_doubleSpinBox_gain2_2_valueChanged(double arg1);

    void on_doubleSpinBox_gain3_2_valueChanged(double arg1);

    void on_checkBox_mono2_clicked(bool checked);

    void on_checkBox_mono1_clicked(bool checked);

    void on_doubleSpinBox_flyback_valueChanged(double arg1);

    void on_checkBox_fastblank_clicked(bool checked);

    void on_checkBox_slowblank_clicked(bool checked);

    void on_doubleSpinBox_laserpower_valueChanged(double arg1);

    void on_checkBox_mono3_clicked(bool checked);

    void on_lineEdit_pathname_editingFinished();

    void on_checkBoxAC_clicked(bool checked);

    void on_checkBox_showoverlay_clicked(bool checked);

    void on_checkBox_showframenumber_clicked(bool checked);

    void on_checkBox_showposition_clicked(bool checked);

    void on_checkBox_showcrosshairs_clicked(bool checked);

    void on_checkBox_showscalebars_clicked(bool checked);

    void on_checkBox_showexposure_clicked(bool checked);

    void on_checkBox_showoverlayimage_clicked(bool checked);

    void on_pushButton_savedisplaytooverlay_clicked();

    void on_pushButton_depthstart_clicked();

    void on_pushButton_depthend_clicked();

    void on_doubleSpinBox_depthstart_valueChanged(double arg1);

    void on_doubleSpinBox_depthend_valueChanged(double arg1);

    void on_doubleSpinBox_micronperslice_2_valueChanged(double arg1);

    void on_doubleSpinBox_powerstart_valueChanged(double arg1);

    void on_doubleSpinBox_powerend_valueChanged(double arg1);

    void on_doubleSpinBox_lengthscale_valueChanged(double arg1);

    void on_pushButton_fastzstack_clicked();

    void on_pushButton_precisezstack_clicked();

    void on_spinBox_imagesx_valueChanged(int arg1);

    void on_spinBox_imagesy_valueChanged(int arg1);

    void on_doubleSpinBox_stridex_valueChanged(double arg1);

    void on_doubleSpinBox_stridey_valueChanged(double arg1);

    void on_pushButton_mosaic2d_clicked();

    void on_comboBox_magnification_currentIndexChanged(const QString &arg1);

    void on_checkBox_showrois_clicked(bool checked);

    void on_actionAnalysis_Window_triggered(bool checked);

    void on_checkBox_showanalysis_clicked(bool checked);

    void on_checkBox_computeroitraces_clicked(bool checked);

    void on_checkBox_computehistograms_clicked(bool checked);

    void on_pushButton_savedelay_clicked();

    void on_spinBox_clockmult_valueChanged(int arg1);

    void on_checkBox_acquirepreview_clicked(bool checked);

    void on_spinBox_totalzslices_precise_valueChanged(int arg1);

    void on_spinBox_fragmentsize_valueChanged(int arg1);

    void on_checkBox_fragment_clicked(bool checked);

    void on_pushButton_clicked();

    void on_pushButtonZeroAcq_clicked();

    void on_comboBox_linesperframe_currentIndexChanged(int index);

    void on_pushButton_mosaic3d_clicked();

    void on_pushButton_mosaic3d_fast_clicked();

    void on_checkBox_save1_clicked(bool checked);

    void on_checkBox_save2_clicked(bool checked);

    void on_checkBox_save3_clicked(bool checked);

    void on_checkBox_sumacquire_clicked(bool checked);

    void on_checkBox_stoptrigger_clicked(bool checked);

    void on_checkBox_lockadc_clicked(bool checked);

    void on_actionManual_triggered();

    void on_checkBox_lockfast_clicked(bool checked);

    void on_doubleSpinBox_fastfreq_valueChanged(double arg1);

    void on_doubleSpinBox_fastdelay_valueChanged(double arg1);

    void on_doubleSpinBox_fastwidth_valueChanged(double arg1);

    void on_doubleSpinBox_slowwidth_valueChanged(double arg1);

    void on_doubleSpinBox_slowdelay_valueChanged(double arg1);

    void on_checkBox_monitormerge_clicked(bool checked);

    void on_spinBox_fastzspeed_valueChanged(int arg1);

    void on_checkBoxSine_rawcprocessing_clicked(bool checked);

    void on_checkBox_motorizedrotation_clicked(bool checked);

    void on_pushButton_zeroangle_clicked();

    void on_doubleSpinBox_radius_valueChanged(double arg1);

    void on_checkBox_fastprocess_clicked(bool checked);

    void on_checkBox_flipx_clicked(bool checked);

    void on_checkBox_flipy_clicked(bool checked);

    void on_pushButton_retract_clicked();

    void on_pushButton_lasercalibration_clicked();

private:

    void keyPressEvent(QKeyEvent * e);
    void keyReleaseEvent(QKeyEvent * e);
    void HandleKeyboardEvent(QKeyEvent * e, bool down, bool externalcapture);
    void closeEvent(QCloseEvent * e);

    //void mousePressEvent(QMouseEvent * e);
    //void mouseMoveEvent(QMouseEvent * e);
    //void enterEvent(QEvent * e);
    //void leaveEvent(QEvent * e);
    //void wheelEvent(QWheelEvent *e);

    //stop asdw type motion on focus loss
    void focusOutEvent(QFocusEvent *e);
    //void focusInEvent(QFocusEvent *e);

    //need a lock motor commands button, to prevent accidental
    //keystroke motion


};

#endif // MAINWINDOW_H
